package com.ljx.threadTest.threadEnum;

import java.util.Arrays;

/**
 * @author 李加喜
 * @Package com.ljx.threadTest.config
 * @date 2024-05-29 10:31
 */
public interface ErrorCode extends BaseErrorCode {
    /**
     * 自定义错误码
     *
     * @param code 错误码
     * @param name 错误信息
     * @return
     */
    static ErrorCode of(int code, String name) {
        return new CustomErrorCode(code, name);
    }

    /**
     * 自定义错误码
     *
     * @param appCode    应用码
     * @param moduleCode 模块码
     * @param code       错误码
     * @param name       错误信息
     * @return
     */
    static ErrorCode of(int appCode, int moduleCode, int code, String name) {
        return of(name, appCode, moduleCode, code);
    }

    /**
     * 自定义错误码
     *
     * @param moduleCode 模块码
     * @param code       错误码
     * @param name       错误信息
     * @return
     */
    static ErrorCode of(int moduleCode, int code, String name) {
        return of(name, moduleCode, code);
    }

    /**
     * @param errorCode
     * @return
     */
    static ErrorCode of(BaseErrorCode errorCode) {
        return new CustomErrorCode(errorCode.getRealApp(), errorCode.getRealModule(), errorCode.getCode(), errorCode.getName());
    }

    /**
     * 格式化错误码：对errorCode中的getName()用 params进行格式化
     *
     * @param errorCode 原始错误码
     * @param params    参数
     * @return
     */
    static ErrorCode format(BaseErrorCode errorCode, Object... params) {
        return new CustomErrorCode(errorCode.getApp(), errorCode.getModule(), errorCode.getCode(), String.format(errorCode.getName(), params));
    }

    /**
     * 自定义错误码
     * <li> codeParts 长度为1时，codeParts[0]表示错误码</li>
     * <li> codeParts 长度为2时，codeParts[0]表示模块编码，codeParts[1]表示错误码</li>
     * <li> codeParts 长度为3时，codeParts[0]表示应用编码，codeParts[1]表示模块编码，codeParts[2]表示错误码</li>
     * <li> codeParts 长度为>3时，codeParts的累计值表示错误码</li>
     *
     * @param name      错误信息
     * @param codeParts codeParts累计后即为真实的错误码
     * @return
     */
    static ErrorCode of(String name, int... codeParts) {
        if (codeParts.length == 1) {
            return new CustomErrorCode(codeParts[0], name);
        }
        if (codeParts.length == 2) {
            return new CustomErrorCode(codeParts[0], codeParts[1], name);
        }
        if (codeParts.length == 3) {
            return new CustomErrorCode(codeParts[0], codeParts[1], codeParts[2], name);
        }
        int code = Arrays.stream(codeParts).sum();
        return new CustomErrorCode(code, name);
    }


    /**
     * 检查 应用编码、模块编码、错误码的合法性：
     * <li>1. 如果应用编码 大于0 ，则必须满足：应用编码的位数 大于 错误码的位数</li>
     * <li>2. 如果模块编码 大于0 ，则必须满足：模块编码的位数 大于 错误码的位数</li>
     * <li>2. 如果应用编码和模块编码 都大于0 ，则必须满足：应用编码的位数 大于 模块码的位数</li>
     *
     * @param app    应用编码
     * @param module 模块编码
     * @param code   错误码
     */
    static void check(int app, int module, int code) {
        if (module > 0) {
            if (getNumLength(module) <= getNumLength(code)) {
                //参数module的位数必须大于参数code的位数
                throw new IllegalArgumentException(String.format("参数[module=%d]的位数必须大于参数[code=%d]", module, code));
            }
        }
        if (app > 0) {
            if (module > 0 && getNumLength(app) <= getNumLength(module)) {
                //参数app的位数必须大于参数module的位数
                throw new IllegalArgumentException(String.format("参数[app=%d]的位数必须大于参数[module=%d]", app, module));
            }
            if (getNumLength(app) <= getNumLength(code)) {
                //参数app的位数必须大于参数code的位数
                throw new IllegalArgumentException(String.format("参数[app=%d]的位数必须大于参数[code=%d]", app, code));
            }
        }
    }

    /**
     * 获取数字的位数
     *
     * @param num 数字
     * @return 数字的位数
     */
    static int getNumLength(int num) {
        num = num > 0 ? num : -num;
        return String.valueOf(num).length();
    }
}
